/********************************** (C) COPYRIGHT *******************************
 * File Name          : main.c
 * Author             : WCH
 * Version            : V1.0.0
 * Date               : 2021/06/06
 * Description        : Main program body.
 *********************************************************************************
 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/

/*
 *@Note
IAP upgrade routine:
Support serial port and USB for FLASH burning

1. Use the IAP download tool to realize the download PA0 floating (default pull-up input)
2. After downloading the APP, connect PA0 to ground (low level input), and press the reset
button to run the APP program.
Note: FLASH operation keeps the frequency below 100Mhz, it is recommended that the main
frequency of IAP be below 100Mhz

*/

// #include "debug.h"
// #include "ch32v30x_usbotg_device.h"
// #include "ch32v30x_usbhs_device.h"
#include "ch32v30x_gpio.h"
#include "iap.h"

#define BOOT_SKIP_KEY ((uint16_t)0x4286)
#define BOOT_ONCE_KEY ((uint16_t)0x8567)

#define FLASH_START_ADDR 0x0801FE00UL
#define FLASH_OFFSET_FIRMWARE_VERSION 2UL
#define FLASH_OFFSET_BOOT_KEY 4UL
#define FLASH_ADDR_FIRMWARE_VERSION (FLASH_START_ADDR + FLASH_OFFSET_FIRMWARE_VERSION)
#define FLASH_ADDR_BOOT_KEY (FLASH_START_ADDR + FLASH_OFFSET_BOOT_KEY)

extern u8 End_Flag;
/*********************************************************************
 * @fn      IAP_2_APP
 *
 * @brief   IAP_2_APP program.
 *
 * @return  none
 */
void IAP_2_APP(void)
{
    //    USBHS_Device_Init( DISABLE );
    //    NVIC_DisableIRQ( USBHS_IRQn );
    //    USBHSD->HOST_CTRL=0x00;
    //    USBHSD->CONTROL=0x00;
    //    USBHSD->INT_EN=0x00;
    //    USBHSD->ENDP_CONFIG=0xFFffffff;
    //    USBHSD->CONTROL&=~USBHS_DEV_PU_EN;
    //    USBHSD->CONTROL|=USBHS_ALL_CLR|USBHS_FORCE_RST;
    //    USBHSD->CONTROL=0x00;
    // Delay_Ms(50);
    // printf("jump APP\r\n");
    // Delay_Ms(10);

    NVIC_EnableIRQ(Software_IRQn);
    NVIC_SetPendingIRQ(Software_IRQn);
}
/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    /* Get current firmware version and boot key */
    uint16_t current_firmware_version = *(volatile uint16_t *)(FLASH_ADDR_FIRMWARE_VERSION);
    uint16_t boot_key = *(volatile uint16_t *)(FLASH_ADDR_BOOT_KEY);

    /* Init */
    SystemCoreClockUpdate();
    // Delay_Init();
    // USART_Printf_Init(115200);
    
    // printf("---\r\n");
    // printf("version: %d.%d\r\n", current_firmware_version >> 8, current_firmware_version & 0xff);
    // printf("boot_key: %#x\r\n", boot_key);

    switch (boot_key)
    {
    case BOOT_SKIP_KEY:
        if (PA0_Check() != 0)
        {
            IAP_2_APP();
            while (1)
                ;
        }
        break;
    case BOOT_ONCE_KEY:
        FLASH_Unlock();
        FLASH_ProgramHalfWord(FLASH_ADDR_BOOT_KEY, BOOT_SKIP_KEY);
        FLASH_Lock();
        boot_key = *(volatile uint16_t *)(FLASH_ADDR_BOOT_KEY);
        break;

    default:
        break;
    }

    USART1_CFG(57600);

    // /* USB20 device init */
    // USBHS_RCC_Init( );
    // USBHS_Device_Init( ENABLE );
    // NVIC_EnableIRQ( USBHS_IRQn );

    // USBOTG_Init( );
    while (1)
    {

        if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
        // if ((USART1->STATR & USART_FLAG_RXNE) != (uint16_t)RESET)
        {
            UART_Rx_Deal();
        }
        IWDG_ReloadCounter();
        if (End_Flag)
        {
            //  Delay_Ms(10);
            IAP_2_APP();
            while (1)
                ;
        }
    }
}
